<template>
  <a-col
    v-if="formFlag"
    :span="theSpan"
    :md="theMd"
    :sm="theSm"
    :xs="theXs"
    :lg="theLg"
    :xl="theXl"
    :xxl="theXxl"
  >
    <a-form-model-item
      layout="vertical"
      :colon="false"
      :ref="prop"
      :required="required"
      :label="
        label != ''
          ? labelLh
            ? label + ':' + imageList.length + '/' + limitNum
            : label
          : '  '
      "
      :prop="prop"
      :labelCol="theLabelCol"
      :wrapperCol="theWrapperCol"
    >
      <template v-if="type === 'files'">
        <a-upload-dragger
          name="file"
          :multiple="multiple"
          :action="actionUrl"
          :disabled="disabled"
          :fileList="imageList"
          :headers="headers"
          @change="handleImageChange"
        >
          <p class="ant-upload-drag-icon">
            <a-icon type="inbox" />
          </p>
          <p class="ant-upload-text">点击或者拖拽文件到此区域上传</p>
          <p class="ant-upload-hint">
            <span v-if="multiple">支持单个或批量上传</span>
            <span v-else>仅支持单个文件上传</span>
          </p>
        </a-upload-dragger>
      </template>
      <template v-if="type === 'img'">
        <a-upload
          listType="picture-card"
          :action="actionUrl"
          :beforeUpload="beforeImageUpload"
          :disabled="disabled"
          :fileList="imageList"
          :headers="headers"
          :multiple="multiple"
          @change="handleImageChange"
          @preview="handleImagePreview"
        >
          <div v-if="imageList.length < limitNum && !disabled">
            <a-icon :type="imageLoading ? 'loading' : 'plus'" />
            <div class="ant-upload-text">上传</div>
          </div>
          <div v-if="imageList.length === 0 && disabled">
            <a-icon type="file-excel" :style="{ fontSize: '20px' }" />
            <div class="ant-upload-text">无文件</div>
          </div>
        </a-upload>
        <viewer
          :images="previewImage"
          ref="viewer"
          align="center"
          style="height: 100%"
          :hidden="handleImageCancel"
        >
          <img
            style="max-width: 100%; max-height: 90%"
            v-for="src in previewImage"
            :src="src"
            :key="src"
          />
        </viewer>
        <a-modal
          :closable="false"
          footer=""
          :maskClosable="false"
          v-model="showUploadingModal"
        >
          <div style="text-align: center">
            <a-spin size="large" :tip="alertNotice + '...'"></a-spin>
          </div>
        </a-modal>
      </template>
      <template v-if="type === 'video'">
        <a-upload
          listType="picture-card"
          :action="actionUrl"
          :beforeUpload="beforeImageUpload"
          :disabled="disabled"
          :fileList="imageList"
          :headers="headers"
          :multiple="multiple"
          @change="handleImageChange"
          @preview="handleVideoPreview"
        >
          <div v-if="imageList.length < limitNum && !disabled">
            <a-icon :type="imageLoading ? 'loading' : 'plus'" />
            <div class="ant-upload-text">上传</div>
          </div>
          <div v-if="imageList.length === 0 && disabled">
            <a-icon type="file-excel" :style="{ fontSize: '20px' }" />
            <div class="ant-upload-text">无文件</div>
          </div>
        </a-upload>
        <a-modal
          v-model="showVideoFlag"
          :maskClosable="false"
          footer=""
          width="80%"
        >
          <div class="video" style="margin-top: 40px">
            <video-player
              class="video-player vjs-custom-skin"
              ref="videoPlayer"
              :playsinline="true"
              :options="playerOptions"
            >
            </video-player>
          </div>
        </a-modal>
        <a-modal
          :closable="false"
          footer=""
          :maskClosable="false"
          v-model="showUploadingModal"
        >
          <div style="text-align: center">
            <a-spin size="large" :tip="alertNotice + '...'"></a-spin>
          </div>
        </a-modal>
      </template>
    </a-form-model-item>
  </a-col>
  <!--  <div v-else>-->
  <!--  </div>-->
</template>
<script>
import { videoPlayer } from "vue-video-player";
import "vue-video-player/src/custom-theme.css";
import "video.js/dist/video-js.css";
import { fileShowUrl, fileUploadUrl } from "@/services/system/api";
import { getFileTypeByID } from "@/services/system/api";
import { isEmptyStr } from "@/utils/util";
export default {
  name: "ZhUpload",
  components: {
    videoPlayer,
  },
  props: {
    required: {
      type: Boolean,
      default: false,
    },
    prop: {
      type: String,
      default: "",
    },
    // 上传组件类型 {'img': '图片', 'files': '文件','video':'视频'}
    type: {
      type: String,
      default: "img",
    },
    dictFileId: {
      //文件字典表主键  校验文件类型是否允许上传
      type: String,
      default: null,
    },
    showLimitNum: {
      //展示限制文件数
      type: Boolean,
      default: false,
    },
    // 是否在form中使用
    formFlag: {
      type: Boolean,
      default: true,
    },
    label: {
      type: String,
      default: "",
      required: false,
    },
    defaultImageList: {
      type: [Array, Object],
      default: function () {
        return [];
      },
      required: false,
    },
    // 视频资源类型及路径
    sources: {
      type: Array,
      required: false,
    },
    // fileTypeList: {
    //   type: Array,
    //   default: function () {
    //     return []
    //   },
    //   required: false,
    // },
    limitSize: {
      type: Number,
      default: 2048,
      required: false,
    },
    limitNum: {
      type: Number,
      default: 1,
      required: false,
    },
    // 上传的地址
    actionUrl: {
      type: String,
      default: fileUploadUrl,
      required: false,
    },
    // 是否支持多选文件，ie10+ 支持。开启后按住 ctrl 可选择多个文件。
    multiple: {
      type: Boolean,
      default: false,
      required: false,
    },
    disabled: {
      type: Boolean,
      default: false,
      required: false,
    },
    labelCol: {
      type: Object,
      default: function () {
        return null;
      },
    },
    //需要为输入控件设置布局样式时，使用该属性，用法同 labelCol
    wrapperCol: {
      type: Object,
      default: function () {
        return null;
      },
    },
    //≥768px
    md: {
      type: Number,
      default: undefined,
    },
    //≥576px
    sm: {
      type: Number,
      default: undefined,
    },
    //<576px
    xs: {
      type: Number,
      default: undefined,
    },
    //≥992px
    lg: {
      type: Number,
      default: undefined,
    },
    //≥1200px
    xl: {
      type: Number,
      default: undefined,
    },
    //≥1600px
    xxl: {
      type: Number,
      default: undefined,
    },
    labelLh: {
      type: Boolean,
      default: true,
    },
    span: Number,
  },
  watch: {
    defaultImageList(newVal) {
      if (newVal instanceof Array) {
        this.imageList = newVal;
      } else this.imageList.push(newVal);
    },
  },
  data() {
    return {
      fileTypeList: [],
      theLabelCol: this.labelCol
        ? this.labelCol
        : this.$parent.$options.parent.labelCol,
      theWrapperCol: this.wrapperCol
        ? this.wrapperCol
        : this.$parent.$options.parent.wrapperCol,
      theSpan: this.getSpan(),
      theMd: this.getMd(),
      theSm: this.getSm(),
      theXs: this.getXs(),
      theLg: this.getLg(),
      theXl: this.getXl(),
      theXxl: this.getXxl(),
      mySpan: null,
      headers: {
        authorization: "",
      },
      alertNotice: "",
      showUploadingModal: false,
      imageLoading: false,
      previewVisible: false,
      previewImage: [],
      imageList: [],
      showVideoFlag: false,
      playerOptions: {
        //播放速度
        playbackRates: [0.5, 1.0, 1.5, 2.0],
        //如果true,浏览器准备好时开始回放。
        autoplay: false,
        // 默认情况下将会消除任何音频。
        muted: false,
        // 导致视频一结束就重新开始。
        loop: false,
        // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频（如果浏览器支持）
        preload: "auto",
        language: "zh-CN",
        // 将播放器置于流畅模式，并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字（例如"16:9"或"4:3"）
        aspectRatio: "16:9",
        // 当true时，Video.js player将拥有流体大小。换句话说，它将按比例缩放以适应其容器。
        fluid: true,
        //你的封面地址
        poster: "",
        //允许覆盖Video.js无法播放媒体源时显示的默认信息。
        notSupportedMessage: "此视频暂无法播放，请稍后再试",
        controlBar: {
          timeDivider: true,
          durationDisplay: true,
          remainingTimeDisplay: false,
          //全屏按钮
          fullscreenToggle: true,
        },
        sources: [],
      },
    };
  },
  created() {
    this.imageList = this.defaultImageList;
    if (this.type === "video" && this.sources) {
      this.playerOptions.sources = this.sources;
      for (let i = 0; i < this.playerOptions.sources.length; i++) {
        let param = {};
        param.url = this.playerOptions.sources[i].src;
        let uuid = "avatar";
        param.name = "mp4";
        param.uid = uuid;
        param.status = "done";
        this.imageList.push(param);
      }
    }
    this.headers.authorization = "Bearer " + this.$store.state.user.token;
    if (!isEmptyStr(this.dictFileId)) {
      const param = {};
      param.id = this.dictFileId;
      this.$http.post(getFileTypeByID, param).then((res) => {
        this.fileTypeList = res.result;
      });
    }
  },
  methods: {
    handleImageChange(info) {
      if (info.file.status === "done") {
        this.showUploadingModal = false;
        this.$message.success("文件上传成功！");
      }
      let fileList = [...info.fileList];
      fileList = fileList.map((file) => {
        if (file.response) {
          const res = file.response.result.file;
          file.showId = res.showId;
          file.url = fileShowUrl + res.showId;
          if (this.type === "video") {
            let video = {};
            video.type = "video/mp4";
            video.src = file.url;
            this.playerOptions.sources.push(video);
          }
        }
        return file;
      });
      this.imageList = fileList;
      this.$emit("handleChange", this.imageList);
    },
    getSpan(data) {
      if (this.span) {
        this.mySpan = this.span;
        return this.span;
      }
      let span = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        span = parent.span;

        if (span === null || span === undefined) {
          let name = parent.$options.name;
          if (name === "ZhForm") {
            this.mySpan = undefined;
            return undefined;
          }
          return this.getSpan(parent);
        } else {
          this.mySpan = span;
          return span;
        }
      } else {
        this.mySpan = undefined;
        return undefined;
      }
    },
    getMd(data) {
      if (this.mySpan) {
        return undefined;
      } else {
        this.getSpan();
      }
      if (this.md) {
        return this.md;
      }
      let md = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        md = parent.md;
        if (md === null || md === undefined) {
          return this.getMd(parent);
        } else {
          return md;
        }
      } else {
        return undefined;
      }
    },
    getSm(data) {
      if (this.mySpan) {
        return undefined;
      } else {
        this.getSpan();
      }
      if (this.sm) {
        return this.sm;
      }
      let sm = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        sm = parent.sm;
        if (sm === null || sm === undefined) {
          return this.getSm(parent);
        } else {
          return sm;
        }
      } else {
        return undefined;
      }
    },
    getXs(data) {
      if (this.mySpan) {
        return undefined;
      } else {
        this.getSpan();
      }
      if (this.xs) {
        return this.xs;
      }
      let xs = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        xs = parent.xs;
        if (xs === null || xs === undefined) {
          return this.getXs(parent);
        } else {
          return xs;
        }
      } else {
        return undefined;
      }
    },
    getLg(data) {
      if (this.mySpan) {
        return undefined;
      } else {
        this.getSpan();
      }
      if (this.lg) {
        return this.lg;
      }
      let lg = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        lg = parent.lg;
        if (lg === null || lg === undefined) {
          return this.getLg(parent);
        } else {
          return lg;
        }
      } else {
        return undefined;
      }
    },
    getXl(data) {
      if (this.mySpan) {
        return undefined;
      } else {
        this.getSpan();
      }
      if (this.xl) {
        return this.xl;
      }
      let xl = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        xl = parent.xl;
        if (xl === null || xl === undefined) {
          return this.getXl(parent);
        } else {
          return xl;
        }
      } else {
        return undefined;
      }
    },
    getXxl(data) {
      if (this.mySpan) {
        return undefined;
      } else {
        this.getSpan();
      }
      if (this.xxl) {
        return this.xxl;
      }
      let xxl = null;
      let parent = null;
      if (data) {
        parent = data.$parent;
      } else {
        parent = this.$parent;
      }
      if (parent) {
        xxl = parent.xxl;
        if (xxl === null || xxl === undefined) {
          return this.getXxl(parent);
        } else {
          return xxl;
        }
      } else {
        return undefined;
      }
    },
    beforeImageUpload(file) {
      return new Promise(async (resolve, reject) => {
        if (!isEmptyStr(this.dictFileId)) {
          const fileOrigName = file.name; //文件名+后缀名
          const last_len = fileOrigName.lastIndexOf(".");
          const len = fileOrigName.length;
          let hz = fileOrigName.substring(last_len + 1, len);
          let macthFlag = false;
          for (var i = 0; i < this.fileTypeList.length; i++) {
            if (hz.toLowerCase() == this.fileTypeList[i]) {
              macthFlag = true;
            }
          }
          if (!macthFlag) {
            this.$message.error(`您上传的文件格式不正确`);
            return reject(new Error(`您上传的文件格式不正确`));
          }
        }

        const limitSize = file.size / 1024 / 1024 < this.limitSize;
        if (!limitSize) {
          this.$message.error(`文件大小不能大于${this.limitSize}MB`);
          return reject(new Error(`文件大小不能大于${this.limitSize}MB`));
        }
        // this.$message.info('文件正在上传中...');
        if (file.size / 1024 / 1024 >= 50) {
          this.alertNotice = "该文件较大，上传所需时间较长，请等待";
        } else {
          this.alertNotice = "文件上传中";
        }
        this.showUploadingModal = true;
        return resolve(true);
      });
    },
    handleImagePreview() {
      this.previewImage = [];
      for (let i = 0; i < this.imageList.length; i++) {
        this.previewImage.push(this.imageList[i].url);
      }
      const viewer = this.$refs["viewer"].$viewer;
      viewer.show();
      this.$emit("handlePreview", this.imageList);
    },
    handleImageCancel() {
      this.previewImage = [];
      this.$emit("handleCancel", this.imageList);
    },
    handleVideoPreview() {
      this.showVideoFlag = true;
    },
  },
};
</script>

<style scoped lang="scss">
.video {
  display: inline-block;
  width: 100%;
  text-align: center;
  line-height: 100px;
  border: 1px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;
  position: relative;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
  margin-right: 4px;
  .vjs-custom-skin {
    ::v-deep .video-js {
      .vjs-big-play-button {
        font-size: 2.5em;
      }
    }
  }
}
.video:hover {
  display: block;
}
</style>
